前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# async/await使用

30 秒速记

  • async 函数总是返回 Promise;await 等一个 Promise 有结果再往下走
  • await 只暂停当前这个 async 函数,事件循环照转,别的请求照样处理
  • 互不依赖的请求别连着 await,用 Promise.all 并发;有依赖的才串行
  • 错误用 try/catch 接,但只接得住被 await 的;没 await 的 Promise 报错会漏掉
  • 同步的 CPU 密集计算照样卡死整个进程,await 救不了

async/await 让异步代码写起来像同步,但它只暂停当前这个函数,不会卡住整个线程。 你可以把 await 理解成「这个函数先挂起,结果回来了再接着往下执行」,挂起期间事件循环继续处理其他回调和请求。它其实是 Promise 的语法糖,async 函数一定返回 Promise。最常见的问题是把本来能并发的请求写成一串 await,白白多等;另一个是忘了 await,错误就跑出 try/catch 了。

async function slow() {
  const a = await fetchA()   // 等 1s
  const b = await fetchB()   // 再等 1s,总共 2s
}
async function fast() {
  const [a, b] = await Promise.all([fetchA(), fetchB()])  // 同时发,总共 1s
}
@前端进阶之旅: 代码已经复制到剪贴板

理解「async/await使用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 event-loop 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

async/await 是 Promise 的语法糖,用一段代码就能看清它的执行时机:

console.log('A')

async function run() {
  console.log('B')
  await null               // 从这里挂起,后面的代码进微任务队列
  console.log('D')
}

run()
console.log('C')
// 输出:A B C D
@前端进阶之旅: 代码已经复制到剪贴板

run() 调用时同步执行到第一个 await,打印 B;遇到 await 函数挂起,控制权回到调用方,所以先打印 C;同步代码跑完后,微任务队列里的「await 后续」执行,打印 D。这说明 await 只挂起当前函数,并没有阻塞外面的代码。

错误处理是第二个要点。await 一个被拒绝的 Promise 会在那一行抛出异常,所以可以用 try/catch:

async function load() {
  try {
    const res = await fetch('/api/user')
    if (!res.ok) throw new Error('HTTP ' + res.status)
    return await res.json()
  } catch (err) {
    console.error('加载失败', err.message)
    return null
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

注意 return await 在 try 里是有意义的:只写 return res.json() 的话,json() 解析失败的错误不会被这个 catch 接住。

第三个要点是并发。连续写 await a(); await b() 是串行的,两个互不依赖的请求应该先同时发出去,再一起等:await Promise.all([a(), b()])。如果并发数量可能很大(比如几千个文件),就要限制同时进行的数量,避免把下游打挂。

面试官追问

追问 1下面这段先打印什么?setTimeout(() => console.log(1)); (async () => { await null; console.log(2) })(); console.log(3)
参考回答

3 2 1。同步的 3 先出;await 之后的代码进微任务,同步代码跑完立刻执行,打印 2;setTimeout 是宏任务,最后打印 1。

追问 2try { doSave() } catch (e) {},doSave 是 async 的,里面抛错能接住吗?
参考回答

接不住,没 await 的话 doSave() 只是返回一个被拒绝的 Promise,try 块早就结束了,最后变成 unhandledRejection。改成 await doSave()。

追问 3一个页面要拉用户信息、订单、推荐三个接口,互不依赖,怎么写最快?
参考回答

const [user, orders, recs] = await Promise.all([getUser(), getOrders(), getRecs()])。如果某个失败了也想展示其他的,用 Promise.allSettled,再逐个看 status。

追问 4接口里 await 了一个 5s 的 CPU 计算函数,其他请求会被卡住吗?
参考回答

会,如果那个函数本身是同步算的(比如大循环、JSON.parse 巨大字符串),包成 async 也没用,主线程被占着谁都跑不了。要么拆片让出事件循环,要么丢给 worker_threads。

追问 5用户点了取消,正在 await 的请求能停下来吗?
参考回答

Promise 本身没有取消机制,要靠 AbortController:把 signal 传给 fetch(url, { signal }),取消时 controller.abort(),await 那里会抛 AbortError。

# async/await使用

# 快速上手理解

30 秒速记

  • getSyncTime 返回 Promise,500ms 后 resolve 出耗时 → 最底层是 Promise
  • getSyncData await 它再拼字符串 → getData await 再打印,一层层往上等
  • 每一层 async 函数都返回 Promise,所以上层能接着 await
  • setTimeout 回调里抛的错,外面那层 try/catch 接不住,要在回调里自己 reject
  • 定时器只保证「至少等这么久」,打印出来可能是 501、503,别断言正好 500

这段例子演示的是 await 一层层等结果:最底层用 Promise 包一个定时器,上面两层 async 函数逐级 await,最后打印出耗时。 跑完你会看到大约 500ms 后控制台输出 endTime - startTime = 501 这样的数字。读这段代码要注意两点:一是 getSyncTime 里那个 try/catch 其实只包住了创建定时器的同步代码,回调里出错它管不着;二是三层函数虽然写法像同步,getData() 调用后会立刻返回一个 Promise,后面的代码不会等它。

function getSyncTime() {
  return new Promise((resolve, reject) => {
    const start = Date.now()
    setTimeout(() => {
      try {
        resolve(Date.now() - start)   // 回调内部自己兜错
      } catch (err) {
        reject(err)
      }
    }, 500)
  })
}
@前端进阶之旅: 代码已经复制到剪贴板

先复制以下这段代码,在粘贴在chrome的控制台console中,按回车键执行

function getSyncTime() {
  return new Promise((resolve, reject) => {
    try {
      let startTime = new Date().getTime()
      setTimeout(() => {
        let endTime = new Date().getTime()
        let data = endTime - startTime
        resolve( data )
      }, 500)
    } catch ( err ) {
      reject( err )
    }
  })
}

async function getSyncData() {
  let time = await getSyncTime()
  let data = `endTime - startTime = ${time}`
  return data
}

async function getData() {
  let data = await getSyncData()
  console.log( data )
}

getData()

@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1getData() 下一行写 console.log('end'),end 先打印还是耗时先打印?
参考回答

end 先打印。getData() 跑到第一个 await 就挂起返回了,后面的同步代码继续执行,500ms 后才轮到打印耗时。

追问 2测试里断言耗时 === 500,偶尔失败,为什么?
参考回答

setTimeout 的时间是「最少等多久」,主线程忙或者标签页在后台都会推迟回调,后台标签页甚至会被节流到 1s 以上。断言 >= 500 加一个合理上限就行。

追问 3把
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

async/await使用|Nodejs专题系列

# async/await使用

30 秒速记

  • async 函数总是返回 Promise;await 等一个 Promise 有结果再往下走
  • await 只暂停当前这个 async 函数,事件循环照转,别的请求照样处理
  • 互不依赖的请求别连着 await,用 Promise.all 并发;有依赖的才串行
  • 错误用 try/catch 接,但只接得住被 await 的;没 await 的 Promise 报错会漏掉
  • 同步的 CPU 密集计算照样卡死整个进程,await 救不了

async/await 让异步代码写起来像同步,但它只暂停当前这个函数,不会卡住整个线程。 你可以把 await 理解成「这个函数先挂起,结果回来了再接着往下执行」,挂起期间事件循环继续处理其他回调和请求。它其实是 Promise 的语法糖,async 函数一定返回 Promise。最常见的问题是把本来能并发的请求写成一串 await,白白多等;另一个是忘了 await,错误就跑出 try/catch 了。

async function slow() {
  const a = await fetchA()   // 等 1s
  const b = await fetchB()   // 再等 1s,总共 2s
}
async function fast() {
  const [a, b] = await Promise.all([fetchA(), fetchB()])  // 同时发,总共 1s
}
@前端进阶之旅: 代码已经复制到剪贴板

理解「async/await使用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 event-loop 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

async/await 是 Promise 的语法糖,用一段代码就能看清它的执行时机:

console.log('A')

async function run() {
  console.log('B')
  await null               // 从这里挂起,后面的代码进微任务队列
  console.log('D')
}

run()
console.log('C')
// 输出:A B C D
@前端进阶之旅: 代码已经复制到剪贴板

run() 调用时同步执行到第一个 await,打印 B;遇到 await 函数挂起,控制权回到调用方,所以先打印 C;同步代码跑完后,微任务队列里的「await 后续」执行,打印 D。这说明 await 只挂起当前函数,并没有阻塞外面的代码。

错误处理是第二个要点。await 一个被拒绝的 Promise 会在那一行抛出异常,所以可以用 try/catch:

async function load() {
  try {
    const res = await fetch('/api/user')
    if (!res.ok) throw new Error('HTTP ' + res.status)
    return await res.json()
  } catch (err) {
    console.error('加载失败', err.message)
    return null
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

注意 return await 在 try 里是有意义的:只写 return res.json() 的话,json() 解析失败的错误不会被这个 catch 接住。

第三个要点是并发。连续写 await a(); await b() 是串行的,两个互不依赖的请求应该先同时发出去,再一起等:await Promise.all([a(), b()])。如果并发数量可能很大(比如几千个文件),就要限制同时进行的数量,避免把下游打挂。

面试官追问

追问 1下面这段先打印什么?setTimeout(() => console.log(1)); (async () => { await null; console.log(2) })(); console.log(3)
参考回答

3 2 1。同步的 3 先出;await 之后的代码进微任务,同步代码跑完立刻执行,打印 2;setTimeout 是宏任务,最后打印 1。

追问 2try { doSave() } catch (e) {},doSave 是 async 的,里面抛错能接住吗?
参考回答

接不住,没 await 的话 doSave() 只是返回一个被拒绝的 Promise,try 块早就结束了,最后变成 unhandledRejection。改成 await doSave()。

追问 3一个页面要拉用户信息、订单、推荐三个接口,互不依赖,怎么写最快?
参考回答

const [user, orders, recs] = await Promise.all([getUser(), getOrders(), getRecs()])。如果某个失败了也想展示其他的,用 Promise.allSettled,再逐个看 status。

追问 4接口里 await 了一个 5s 的 CPU 计算函数,其他请求会被卡住吗?
参考回答

会,如果那个函数本身是同步算的(比如大循环、JSON.parse 巨大字符串),包成 async 也没用,主线程被占着谁都跑不了。要么拆片让出事件循环,要么丢给 worker_threads。

追问 5用户点了取消,正在 await 的请求能停下来吗?
参考回答

Promise 本身没有取消机制,要靠 AbortController:把 signal 传给 fetch(url, { signal }),取消时 controller.abort(),await 那里会抛 AbortError。

# async/await使用

# 快速上手理解

30 秒速记

  • getSyncTime 返回 Promise,500ms 后 resolve 出耗时 → 最底层是 Promise
  • getSyncData await 它再拼字符串 → getData await 再打印,一层层往上等
  • 每一层 async 函数都返回 Promise,所以上层能接着 await
  • setTimeout 回调里抛的错,外面那层 try/catch 接不住,要在回调里自己 reject
  • 定时器只保证「至少等这么久」,打印出来可能是 501、503,别断言正好 500

这段例子演示的是 await 一层层等结果:最底层用 Promise 包一个定时器,上面两层 async 函数逐级 await,最后打印出耗时。 跑完你会看到大约 500ms 后控制台输出 endTime - startTime = 501 这样的数字。读这段代码要注意两点:一是 getSyncTime 里那个 try/catch 其实只包住了创建定时器的同步代码,回调里出错它管不着;二是三层函数虽然写法像同步,getData() 调用后会立刻返回一个 Promise,后面的代码不会等它。

function getSyncTime() {
  return new Promise((resolve, reject) => {
    const start = Date.now()
    setTimeout(() => {
      try {
        resolve(Date.now() - start)   // 回调内部自己兜错
      } catch (err) {
        reject(err)
      }
    }, 500)
  })
}
@前端进阶之旅: 代码已经复制到剪贴板

先复制以下这段代码,在粘贴在chrome的控制台console中,按回车键执行

function getSyncTime() {
  return new Promise((resolve, reject) => {
    try {
      let startTime = new Date().getTime()
      setTimeout(() => {
        let endTime = new Date().getTime()
        let data = endTime - startTime
        resolve( data )
      }, 500)
    } catch ( err ) {
      reject( err )
    }
  })
}

async function getSyncData() {
  let time = await getSyncTime()
  let data = `endTime - startTime = ${time}`
  return data
}

async function getData() {
  let data = await getSyncData()
  console.log( data )
}

getData()

@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1getData() 下一行写 console.log('end'),end 先打印还是耗时先打印?
参考回答

end 先打印。getData() 跑到第一个 await 就挂起返回了,后面的同步代码继续执行,500ms 后才轮到打印耗时。

追问 2测试里断言耗时 === 500,偶尔失败,为什么?
参考回答

setTimeout 的时间是「最少等多久」,主线程忙或者标签页在后台都会推迟回调,后台标签页甚至会被节流到 1s 以上。断言 >= 500 加一个合理上限就行。

追问 3把 resolve(data) 改成 reject(new Error('timeout')),会发生什么?
参考回答

getSyncData 里的 await 那一行会抛错,后面的拼接不执行,错误一路冒到 getData,也没人接,控制台出现 Uncaught (in promise) Error: timeout。在 getData 里包 try/catch 就能接住。

追问 4有人在 setTimeout 回调里写了 JSON.parse('{'),外层的 try/catch 会 reject 吗?
参考回答

不会,回调执行时外层的 try 早就结束了,异常直接变成全局未捕获错误,这个 Promise 永远停在 pending。所以要在回调内部 try/catch 再 reject。

追问 5要测十个独立任务的耗时,写十行 await getSyncTime(),总共要等多久?
参考回答

大约 5s,因为是一个一个等。改成 await Promise.all(Array.from({ length: 10 }, getSyncTime)),十个定时器同时开始,总共 500ms 左右。

# 在chrome的console中执行结果如下

30 秒速记

  • 控制台先显示 getData() 的返回值 Promise {<pending>},约 500ms 后才打印耗时
  • 说明 async 函数调用后立刻返回 Promise,不会原地等
  • 打印的耗时略大于 500,定时器只保证下限
  • 控制台支持顶层 await,await getData() 会等结果出来再返回
  • Node 里顶层 await 只能用在 ES Module(.mjs 或 "type": "module")

在 Chrome 控制台执行后,先看到一个 Promise {<pending>},过大约半秒才打印出 endTime - startTime = 50x。 第一行是 getData() 的返回值,控制台会把最后一个表达式的值显示出来,因为 async 函数一调用就返回 Promise,这时候定时器还没到点。半秒后定时器回调 resolve,await 一层层往上接着执行,最后 console.log 出耗时。这个现象正好说明 await 只挂起函数本身,调用方是不等的。

← 1.1 快速开始1.3 koa2简析结构 →

fe